Skip to content

Update UserInfo.kt#13

Closed
jkmaina wants to merge 1 commit intoonelogin:developfrom
jkmaina:patch-1
Closed

Update UserInfo.kt#13
jkmaina wants to merge 1 commit intoonelogin:developfrom
jkmaina:patch-1

Conversation

@jkmaina
Copy link
Copy Markdown

@jkmaina jkmaina commented Nov 11, 2022

The preferred_username, updated_at, given_name and family_name fields captured as null on the userinfo object. This is due to a failure on gson.fromJson conversion for fields with underscores.

Proposing adding annotation for resolving this issue.

Best Regards
James

The preferred_username, updated_at, given_name and family_name fields captured as null on the userinfo object. This is due to a failure on gson.fromJson conversion for fields with underscores.

Proposing adding annotation for resolving this issue.

Best Regards
James
@Subterrane Subterrane requested review from Copilot and removed request for kdallan-ol January 7, 2026 21:29
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a deserialization issue where fields with underscores (preferred_username, updated_at, given_name, family_name) in the JSON response were not being mapped correctly to the camelCase Kotlin properties, resulting in null values. The fix adds Gson @SerializedName annotations to map the JSON field names to the Kotlin properties, and introduces a JSONConvertable interface with helper methods for JSON serialization/deserialization.

Key changes:

  • Added @SerializedName annotations to map JSON snake_case fields to Kotlin camelCase properties
  • Introduced JSONConvertable interface with JSON conversion helper methods
  • Added Gson import statements

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@@ -1,12 +1,21 @@
package com.onelogin.oidc.userInfo

import com.google.gson.Gson
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Gson import is used only in the newly added JSONConvertable interface, not in the UserInfo data class itself. Consider moving the JSONConvertable interface and its extension function to a separate utility file to keep concerns separated and avoid coupling the UserInfo data class with Gson implementation details.

Copilot uses AI. Check for mistakes.
Comment on lines +17 to +21
interface JSONConvertable {
fun toJSON(): String = Gson().toJson(this)
}

inline fun <reified T: JSONConvertable> String.toObject(): T = Gson().fromJson(this, T::class.java)
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creating new Gson instances on every serialization/deserialization call is inefficient. Gson objects are thread-safe and intended to be reused. Consider creating a single shared Gson instance to avoid the overhead of repeated instantiation.

Suggested change
interface JSONConvertable {
fun toJSON(): String = Gson().toJson(this)
}
inline fun <reified T: JSONConvertable> String.toObject(): T = Gson().fromJson(this, T::class.java)
private val gson = Gson()
interface JSONConvertable {
fun toJSON(): String = gson.toJson(this)
}
inline fun <reified T: JSONConvertable> String.toObject(): T = gson.fromJson(this, T::class.java)

Copilot uses AI. Check for mistakes.
Comment on lines +15 to +21
) : JSONConvertable

interface JSONConvertable {
fun toJSON(): String = Gson().toJson(this)
}

inline fun <reified T: JSONConvertable> String.toObject(): T = Gson().fromJson(this, T::class.java)
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'Convertable' to 'Convertible'.

Suggested change
) : JSONConvertable
interface JSONConvertable {
fun toJSON(): String = Gson().toJson(this)
}
inline fun <reified T: JSONConvertable> String.toObject(): T = Gson().fromJson(this, T::class.java)
) : JSONConvertible
interface JSONConvertible {
fun toJSON(): String = Gson().toJson(this)
}
inline fun <reified T: JSONConvertible> String.toObject(): T = Gson().fromJson(this, T::class.java)

Copilot uses AI. Check for mistakes.
Subterrane added a commit that referenced this pull request Mar 17, 2026
UserInfo fields with snake_case JSON keys (preferred_username, given_name,
family_name, updated_at) were silently deserializing as null because Gson
performs exact name matching against the camelCase Kotlin property names.

Also changes updatedAt from String? to Long? to match the OIDC spec
(updated_at is a Unix epoch timestamp), adds ProGuard consumer rules to
prevent R8 from stripping Gson model fields, and adds deserialization tests.

Supersedes #6, #13, #16. [no-ado]
@Subterrane
Copy link
Copy Markdown
Collaborator

Thanks for the fix — the @SerializedName annotations are correct and needed.

A couple of concerns:

  • The JSONConvertable interface is unrelated to the serialization bug and should be in a separate PR
  • updatedAt remains as String?, but the OIDC spec defines it as a numeric Unix timestamp — should be Long?
  • The interface name has a typo ("Convertable" → "Convertible")

I've opened PR #23 which combines the annotation fixes from this PR, PR #6, and PR #16, with the correct type, ProGuard rules, and tests.

@Subterrane
Copy link
Copy Markdown
Collaborator

#23

@Subterrane Subterrane closed this Mar 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants